package cease.butter;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;

import cease.http.HttpRequestExecutor;
import cease.http.HttpRequestResult;
import cease.json.JSONUtil;
import cease.urs.Session;
import cease.vo.Butter;
import cease.vo.Message;
import cease.vo.UnreadsCount;
import cease.vo.UploadedPhoto;
import cease.vo.UserInfo;

/**
 * @author dhf
 */
public class BaseExecutor {
    protected HttpRequestExecutor executor = new HttpRequestExecutor();

    protected JSON get(String url, Map<String, String> parameters,
            String charset, Session session) throws ApiException {
        List<NameValuePair> listParams = null;
        if (null != parameters && parameters.size() > 0) {
            listParams = new LinkedList<NameValuePair>();
            for (Entry<String, String> entry: parameters.entrySet()) {
                listParams.add(new BasicNameValuePair(entry.getKey(), entry
                        .getValue()));
            }
        }
        return get(url, listParams, charset, session);
    }

    protected JSON get(String url, List<NameValuePair> parameters,
            String charset, Session session) throws ApiException {
        try {
            HttpRequestResult result = executor.get(url, parameters,
                    getHeaders(session), charset);
            return parseResult(result);
        } catch (IOException e) {
            throw new ApiException(e);
        }
    }

    protected JSON post(String url, List<NameValuePair> parameters,
            String charset, Session session) throws ApiException {
        return post(url, parameters, null, charset, session);
    }

    protected JSON post(String url, List<NameValuePair> parameters,
            List<HttpEntity> entities, String charset, Session session)
            throws ApiException {
        try {
            HttpRequestResult result = executor.post(url, parameters, entities,
                    getHeaders(session), charset);
            return parseResult(result);
        } catch (IOException e) {
            throw new ApiException(e);
        }
    }

    protected JSON parseResult(HttpRequestResult result) throws ApiException {
        if (null == result) {
            throw new IllegalArgumentException("[result] could not be null");
        }
        if (result.getStatus() == 200) {
            JSON json = JSONUtil.parseJSON(result.getContentStr(), JSONUtil
                    .getJsonConfig());
            if (!json.isArray()) {
                JSONObject jo = (JSONObject) json;
                if (null != jo.get("error")) {
                    throw new ApiException(jo.getString("error"));
                }
            }
            return json;
        } else {
            throw new ApiException("Http Status Code : " + result.getStatus());
        }
    }

    protected Collection<Butter> toButterArray(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (!json.isArray()) {
            json = JSONArray.fromObject(json);
        }
        Collection<Butter> butters = JSONUtil.toCollection((JSONArray) json,
                Butter.class);
        return butters;
    }

    protected Butter toButter(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (json.isArray()) {
            json = (JSON) ((JSONArray) json).get(0);
        }
        return JSONUtil.toBean((JSONObject) json, Butter.class);
    }

    protected UserInfo toUserInfo(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (json.isArray()) {
            json = (JSON) ((JSONArray) json).get(0);
        }
        return JSONUtil.toBean((JSONObject) json, UserInfo.class);
    }

    protected Collection<UserInfo> toUserInfoArray(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (!json.isArray()) {
            json = JSONArray.fromObject(json);
        }
        Collection<UserInfo> userinfos = JSONUtil.toCollection(
                (JSONArray) json, UserInfo.class);
        return userinfos;
    }

    protected Collection<Message> toMessageArray(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (!json.isArray()) {
            json = JSONArray.fromObject(json);
        }
        Collection<Message> messages = JSONUtil.toCollection((JSONArray) json,
                Message.class);
        return messages;
    }

    protected Message toMessage(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (json.isArray()) {
            json = (JSON) ((JSONArray) json).get(0);
        }
        return JSONUtil.toBean((JSONObject) json, Message.class);
    }

    protected UnreadsCount toUnreadsCount(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (json.isArray()) {
            json = (JSON) ((JSONArray) json).get(0);
        }
        return JSONUtil.toBean((JSONObject) json, UnreadsCount.class);
    }

    protected UploadedPhoto toUploadedPhoto(JSON json) {
        if (null == json) {
            throw new IllegalArgumentException("[json] could not be null");
        }
        if (json.isArray()) {
            json = (JSON) ((JSONArray) json).get(0);
        }
        return JSONUtil.toBean((JSONObject) json, UploadedPhoto.class);
    }

    private Header[] getHeaders(Session session) {
        Header[] headers = null;
        if (null != session && StringUtils.isNotBlank(session.getCookieStr())) {
            headers = new Header[] {
                new BasicHeader("Cookie", session.getCookieStr())
            };
        }
        return headers;
    }
}
